package cn.exrick.xboot.modules.transport.task;

import cn.exrick.xboot.common.utils.DistanceUtil;
import cn.exrick.xboot.modules.base.enums.OrderStatusEnum;
import cn.exrick.xboot.modules.transport.baoxian.config.InsuranceStatus;
import cn.exrick.xboot.modules.transport.baoxian.service.InsuranceService;
import cn.exrick.xboot.modules.transport.entity.CompanyRoutes;
import cn.exrick.xboot.modules.transport.entity.CompanyWarehouses;
import cn.exrick.xboot.modules.transport.entity.OrderCarInfo;
import cn.exrick.xboot.modules.transport.entity.Orders;
import cn.exrick.xboot.modules.transport.gps.dto.GpsFindDevRequest;
import cn.exrick.xboot.modules.transport.gps.dto.GpsFindDevResponse;
import cn.exrick.xboot.modules.transport.gps.dto.GpsQueryLocationRequest;
import cn.exrick.xboot.modules.transport.gps.dto.GpsQueryLocationResponse;
import cn.exrick.xboot.modules.transport.gps.service.GpsApiService;
import cn.exrick.xboot.modules.transport.mapper.CompanyRoutesMapper;
import cn.exrick.xboot.modules.transport.mapper.CompanyWarehousesMapper;
import cn.exrick.xboot.modules.transport.mapper.OrderCarInfoMapper;
import cn.exrick.xboot.modules.transport.mapper.OrdersMapper;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Iterables;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class Task {

    private final OrderCarInfoMapper orderCarInfoMapper;
    private final InsuranceService insuranceService;
    private final GpsApiService gpsApiService;
    private final OrdersMapper ordersMapper;
    private final CompanyWarehousesMapper companyWarehousesMapper;
    private final CompanyRoutesMapper companyRoutesMapper;

    /**
     * 每小时执行一次（整点执行，避免集群重复执行）
     */
    @Scheduled(cron = "0 0 * * * *")
    public void updateInsuranceStatusHourly() {
        log.info("开始执行保险状态定时更新任务...");
        // 查询需要更新的订单（示例：检查所有未终态的保单）
        List<OrderCarInfo> pendingOrders = orderCarInfoMapper.findPendingReviewOrders(
                InsuranceStatus.TO_BE_REVIEWED.getDesc()
                ,LocalDateTime.now().minusDays(5)
        );
        // 分批处理（避免内存溢出）
        Iterables.partition(pendingOrders, 100).forEach(batch -> {
            batch.forEach(insuranceService::updateSingleOrderStatus);
        });
        log.info("保险状态更新任务完成，共处理{}条记录", pendingOrders.size());
    }
    @Scheduled(cron = "0 0 * * * *")
    public void updateOrderInTransit() {
        log.info("开始执行GPS读取发货状态...");
        // 查询需要更新的订单（示例：检查所有已接单但未发货的订单）
        List<OrderCarInfo> orderCarInfos = orderCarInfoMapper.findAcceptedOrdersCarInfo();
        if (CollectionUtil.isNotEmpty(orderCarInfos)){
            //orderCarInfos 按照订单id分组 校验orderCarInfo 中是否有gpsImei号，如果没有则不进行更新
            orderCarInfos.stream().collect(Collectors.groupingBy(OrderCarInfo::getOrderId))
                    .forEach((orderId, orderCarInfoList) -> {
                        // 检查是否有gpsImei号
                        Optional<OrderCarInfo> first = orderCarInfoList.stream()
                                .filter(orderCarInfo -> StrUtil.isNotBlank(orderCarInfo.getGpsImei())).findFirst();
                        if (first.isPresent()) {
                            //查看实时gps与起运仓距离超过50公里 则更新订单为运输中
                            Orders orders = ordersMapper.selectById(orderId);
                            CompanyRoutes companyRoutes = companyRoutesMapper.selectById(orders.getRouteId());
                            if (companyRoutes == null) {
                                log.warn("订单{}的路线不存在，跳过更新", orderId);
                                return;
                            }
                            //获取起运仓坐标
                            CompanyWarehouses companyWarehouses = companyWarehousesMapper.selectById(companyRoutes.getOriginWarehouseId());
                            if (companyWarehouses == null) {
                                log.warn("订单{}的起运仓不存在，跳过更新", orderId);
                                return;
                            }
                            //获取起运仓坐标
                            String[] coordinates = companyWarehouses.getCoordinates().split(",");
                            if (orders.getAcceptanceTime() != null) {
                                //查询gpsSimei号
                                GpsFindDevRequest gpsFindDevRequest = new GpsFindDevRequest();
                                gpsFindDevRequest.getParams().setImei(first.get().getGpsImei());
                                List<GpsFindDevResponse> devices = gpsApiService.findDevices(gpsFindDevRequest);
                                if(CollectionUtil.isEmpty(devices)){
                                    log.warn("订单{}的GPS设备不存在，跳过更新", orderId);
                                    return;
                                }
                                String gpsSimei = devices.get(devices.size() - 1).getSimei();
                                //查询gps轨迹
                                GpsQueryLocationRequest gpsQueryLocationRequest = new GpsQueryLocationRequest();
                                gpsQueryLocationRequest.getParams().setSimei(gpsSimei);
                                ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
                                gpsQueryLocationRequest.getParams().setTime_begin(orders.getAcceptanceTime().atZone(shanghaiZone).toEpochSecond());
                                gpsQueryLocationRequest.getParams().setTime_end(LocalDateTime.now().atZone(shanghaiZone).toEpochSecond());
                                List<GpsQueryLocationResponse> gpsQueryLocationResponses = gpsApiService.queryLocation(gpsQueryLocationRequest);
                                if (CollectionUtil.isNotEmpty(gpsQueryLocationResponses)) {
                                    GpsQueryLocationResponse gpsQueryLocationResponse = Iterables.getLast(gpsQueryLocationResponses);
                                    if (ObjectUtil.isEmpty(gpsQueryLocationResponse) || StrUtil.isBlank(gpsQueryLocationResponse.getWgs())) {
                                        log.warn("订单{}的GPS数据为空，跳过更新", orderId);
                                        return;
                                    }
                                    double distance = DistanceUtil.calculateDistance(coordinates[0], coordinates[1], gpsQueryLocationResponse.getWgs().split(",")[0], gpsQueryLocationResponse.getWgs().split(",")[1]);
                                    if (distance > 5) {
                                        orders.setStatus(OrderStatusEnum.InTransit.getValue());
                                        orders.setDeliveryTime(LocalDateTime.now());
                                        ordersMapper.updateById(orders);
                                        log.info("订单{}已发货，更新为运输中", orderId);
                                    } else {
                                        log.warn("订单{}未发货，跳过更新", orderId);
                                    }
                                } else {
                                    log.warn("订单{}未接单，跳过更新", orderId);
                                }
                            }else {
                                log.warn("订单{}未接单，跳过更新", orderId);
                            }
                        }
                    });
        }
        log.info("GPS读取发货状态任务完成");
    }
}
